package pCloud.server;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;

import pCloud.service.ProtocolHandle;
import pCloud.transport.Communicator;
import pCloud.transport.EndPointTransportHandle;
import pCloud.transport.TransportHandle;

/**
 * Accepting connections and spawn new threads to deal with them. Two different
 * points of accepting connection: proxy server and database server. Different
 * servers may have different transportation and protocol handler.
 * 
 * Which server is running is specified in the configuration file.
 * 
 * All Acceptor maintains a lists of incoming connections
 */
public abstract class CloudAcceptor {
	ProtocolHandle protocolHandler;
	EndPointTransportHandle serverTransportHandler;
	int port;

	int connectionIndex=0;
	Communicator communicator;

	
	public CloudAcceptor(int port, Communicator comm) throws Exception {
		this.port = port;
		this.communicator = comm;
		init();
	}

	public Communicator getCommunicator(){
		return this.communicator;
	}
	
	private void init() throws Exception {
		serverTransportHandler = this.getServerTransportHandle(port);
	}

	/**
	 * Accepting connection and then initialize the protocol handler
	 * 
	 * @throws Exception
	 */
	public void accept() throws Exception {
		(new CloudThread(this)).start();
	}

	
	public abstract EndPointTransportHandle getServerTransportHandle(int port)
			throws Exception;

	public abstract ProtocolHandle getNewProtocolHandle() throws Exception;
}

class CloudThread extends Thread {
	CloudAcceptor acceptor;

	public CloudThread(CloudAcceptor acceptor) {
		this.acceptor = acceptor;
	}

	public void run() {
		TransportHandle conn;
		ProtocolHandle protocolHandler;
		try {
			while (true) {
				conn = acceptor.serverTransportHandler.accept();
				protocolHandler = acceptor.getNewProtocolHandle();
				protocolHandler.init(conn, acceptor.communicator);
				protocolHandler.startReceiverThread();										
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
